#include "HTMLizer.h"
#include<iostream>
#include<sstream>

using namespace std;

#include "Keywords.h"
#include "Scope.h"
#include "Symbol.h"
#include "SymbolTable.h"
#include "Tokenizer.h"

HTMLizer::HTMLizer(void)
{
	m_pxCurrentScope = NULL;
	m_eScopeType = Scope::eScopeInvalid;
	m_nLineNumber = 1;
	m_cLookAhead = '\0';
}

HTMLizer::~HTMLizer(void)
{
}

void HTMLizer::onNewToken(Scope& inScope, Token& inToken)
{
	char cDelimiter= char(inToken);
	std::string sTokenHTML="";

	switch (cDelimiter) {
		case '&':
			sTokenHTML = "&amp;";
			break;
		case '<':
			sTokenHTML = "&lt;";
			break;
		case '>':
			sTokenHTML = "&gt;";
			break;
		case '"':
			sTokenHTML = "&quot;";
			break;
		case '\t':
			sTokenHTML = "&nbsp;&nbsp;&nbsp;&nbsp;"; 
			//TODO: Replace with string padding function
			break;
		case ' ':
			if(' ' == m_cLookAhead)
			{
				sTokenHTML = "&nbsp;";
			}
			else
			{
				sTokenHTML = inToken.m_sValue;
				m_cLookAhead = cDelimiter;
			}
			break;
		case '\r':
			sTokenHTML = ""; //Otherwise \r\n sequences will produce two <BR/>s 
			//TODO: Replace with lookahead strategy
			break;
		case '\n':
			sTokenHTML ="<BR/>\n"; // \n for human-readability of generated HTML
			break;
		default:
			sTokenHTML = inToken.m_sValue;
			break;
	}

	switch( m_eScopeType)
	{
	case Scope::eScopeCommentC:
	case Scope::eScopeCommentCPP:
	case Scope::eScopePreprocessor:
	case Scope::eScopeLiteral:
		break;

	default:
		if(Keywords::isKeyword(sTokenHTML))
		{
			sTokenHTML = ("<span class=keyword>" + sTokenHTML + "</span>");
		}
		else
		{
			if(inToken.m_bIsDelimiter) break;

			Symbol xSymbol;
			if(inScope.findSymbol(inToken.m_sValue, xSymbol))
			{
				stringstream sLineNumber;
				sLineNumber<<xSymbol.m_xDefinition.m_nLineNumber;

				//<a href="#bookmark">HTML a tag example</a> 
				sTokenHTML="";
				sTokenHTML += "<a href=\"#SL";
				sTokenHTML += sLineNumber.str();
				sTokenHTML += "\">";
				sTokenHTML += inToken.m_sValue;
				sTokenHTML += "</a>";
				
			}
		}
	}

    cout<<sTokenHTML;

	if('\n' == cDelimiter)
		//Intentionally not coupling with switch case, this is not tr functionality
	{
		m_nLineNumber++;
		createNewline();
	}

}

void HTMLizer::createNewline()
{
	createSpanEnd();

	stringstream sLineNumber;
	sLineNumber<<m_nLineNumber;
	std::string sLineHTML="";
	sLineHTML += "</span>\n";
	sLineHTML += "<span id= \"SL";
	sLineHTML += sLineNumber.str();
	sLineHTML += "\">";
	cout<<sLineHTML<<endl;

	createSpanForScope();

}

void HTMLizer::createSpanForScope()
{
	switch(m_eScopeType)
	{
	case Scope::eScopeCommentC:
	case Scope::eScopeCommentCPP:
		cout << "<span class=comment>";
		break;

	case Scope::eScopePreprocessor:
		cout << "<span class=preprocessor>";
		break;

	case Scope::eScopeLiteral:
		cout << "<span class=literal>";
		break;

	}
}

void HTMLizer::createSpanEnd()
{
	switch(m_eScopeType)
	{
	case Scope::eScopeCommentC:
	case Scope::eScopeCommentCPP:
	case Scope::eScopePreprocessor:
	case Scope::eScopeLiteral:
		cout<< "</span>";
		break;

	}
}

void HTMLizer::onScopeEntry(Scope& inNewScope, Scope& inOldScope)
{
	m_pxCurrentScope = &inNewScope;
	m_eScopeType = m_pxCurrentScope->getScopeType();
	createSpanForScope();
}

void HTMLizer::onScopeExit(Scope& inNewScope, Scope& inOldScope)
{
	createSpanEnd();
	m_pxCurrentScope = &inNewScope;
	m_eScopeType = m_pxCurrentScope->getScopeType();

}

void HTMLizer::generateHeader()
{
	cout << "<html>" << endl << "<head>" << endl;
	cout << "<style>" << endl;
	cout << "BODY{font-family:courier;}"<<endl;
	cout << ".keyword{color:rgb(0,0,255);}" << endl;
	cout << ".comment{color:rgb(0,128,0);}" << endl;
	cout << ".preprocessor{color:rgb(0,0,255);}" << endl;
	cout << ".literal{color:rgb(163,21,21);}" << endl;
	cout << ".review{color: #FF5500;}" << endl;
	cout << ".p{font-family:courier;}"<<endl;

//A:link{color:white}
//A:visited{color:yellow	
	cout << "</style>" << endl;

	  
	cout<< "<script type=\"text/javascript\" src=\"prototype.js\"> </script>"<<endl;
	cout<< "<script type=\"text/javascript\" src=\"editinplace.js\"> </script>"<<endl;
	cout<< "</head>"<<endl;

	cout<< "<script type=\"text/javascript\">"<<endl;
    cout<< "    Event.observe(window, 'load', init, false);"<<endl;
    cout<< "    function init() {";
    cout<< "            for (i = 1; i <= 10000; i++){"<<endl;
    cout<< "            var        locationid='SL'+i;"<<endl;
    cout<< "                    EditInPlace.makeEditable( {"<<endl;
    cout<< "                            type: 'textarea',"<<endl;
    cout<< "                    id: locationid,"<<endl;
    cout<< "                            save_url: 'edit.php'"<<endl;
    cout<< "                    } );"<<endl;
    cout<< "            }"<<endl;
    cout<< "    }"<<endl;
	cout<< "</script>"<<endl;

	cout << "<body>" << endl;
	cout << "<span id= \"SL1\">" << endl;

}

void HTMLizer::generateFooter()
{
	cout<<"</span>"<<endl;
	cout << "</body>" << endl << "</html>" << endl;
}

